package com.computergames.server.server.handler;

import com.computergames.server.domain.ClientState;
import com.computergames.server.domain.Deck;
import com.computergames.server.domain.PokerCard;
import com.computergames.server.message.ReadyResponseMessage;
import com.computergames.server.message.cardMessage.BidRequestMessage;
import com.computergames.server.message.cardMessage.BidResponseMessage;
import com.computergames.server.server.session.RoomSessionFactory;
import com.computergames.server.server.session.SessionFactory;
import com.computergames.server.service.Deal.DealStrategy;
import com.computergames.server.service.Deal.DealStrategyFactory;
import com.computergames.server.service.Interface.CheckAndUpdateClientState;
import com.computergames.server.service.getCurrentPlayerStrategy.Bid_GetCurrentPlayerStrategySelector;
import com.computergames.server.util.RedisUtil;
import com.computergames.server.util.SpringUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ChannelHandler.Sharable
public class BidRequestMessageHandler extends SimpleChannelInboundHandler<BidRequestMessage> {
    private static final Map<String, Map<String, Map<String, Integer>>> roomBids = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, AtomicInteger> roomBidCounts = new ConcurrentHashMap<>();


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, BidRequestMessage msg) throws Exception {
        CheckAndUpdateClientState checkAndUpdateClientState = SpringUtil.getBean(CheckAndUpdateClientState.class);
        Bid_GetCurrentPlayerStrategySelector getCurrentPlayerStrategySelector = SpringUtil.getBean(Bid_GetCurrentPlayerStrategySelector.class);
        if(checkAndUpdateClientState.checkState(channelHandlerContext, ClientState.CARD_DEAL)) {
            String roomName = (String)channelHandlerContext.attr(AttributeKey.valueOf("USER_ROOM")).get();
            String player = msg.getPlayer();
            if(!channelHandlerContext.attr(AttributeKey.valueOf("POSITION")).get().equals(player)){
                channelHandlerContext.writeAndFlush(new BidResponseMessage(false, "叫牌错误"));
                return;
            }
            String username = (String)channelHandlerContext.attr(AttributeKey.valueOf("USER_IDENTIFIER")).get();
            RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);
            String roomType = redisUtil.hget(roomName, "roomType").toString();
            DealStrategy<PokerCard> dealStrategy = DealStrategyFactory.getDealStrategy(roomType);
            int bid = msg.getBid();

            if(!getCurrentPlayerStrategySelector.select(roomName, player, bid, roomType)){
                channelHandlerContext.writeAndFlush(new BidResponseMessage(false, "叫牌错误"));
                return;
            }
            AtomicInteger count = roomBidCounts.computeIfAbsent(roomName, k -> new AtomicInteger(0));
            count.incrementAndGet();
            List<Channel> channels = RoomSessionFactory.getRoomSession().getMembersChannel(roomName);


            // 更新房间叫牌信息
            Map<String, Map<String, Integer>> playerBids = roomBids.computeIfAbsent(roomName, k -> new ConcurrentHashMap<>());
            Map<String, Integer> usernameBids = playerBids.computeIfAbsent(player, k -> new ConcurrentHashMap<>());
            usernameBids.put(username, bid);

            if (count.get() == channels.size() || (bid == 3 && roomType.equals("斗地主"))) {
                channels.forEach(channel -> {
                    //checkAndUpdateClientState.updateState(channel, ClientState.GAME_STARTED);
                    channel.writeAndFlush(new BidResponseMessage(true, "叫牌结束"));
                });
                if(roomType.equals("斗地主")){
                    // 默认只有扑克需要发送底牌
                    Deck<PokerCard> deck = ReadyRequestMessageHandler.getInstance().getDeckForRoom(roomName);
                    dealStrategy.dealCards(roomName, deck, playerBids);
                    channels.forEach(channel -> {
                        checkAndUpdateClientState.updateState(channel, ClientState.GAME_STARTED);
                    });
                }
                roomBidCounts.remove(roomName);
            }
        }else{
            channelHandlerContext.writeAndFlush(new BidResponseMessage(false, "请先应答发牌信息再进行叫牌"));
        }
    }

    public static Map<String, Map<String, Map<String, Integer>>> getRoomBids() {
        return Map.copyOf(roomBids);
    }
}
